#include "ui.h"

namespace TGO
{
        TgoUI& GetTgoUI()
        {
                static TgoUI tgoUI;
                return tgoUI;
        }

	bool UIWndProc( UINT message, WPARAM wParam, LPARAM lParam )
	{
		switch( message ) {
		case WM_LBUTTONUP:
			GetTgoUI().LButtonUp();
			return true;
		case WM_LBUTTONDOWN:
			GetTgoUI().LButtonDown();
			return true;
		case WM_RBUTTONUP:
			GetTgoUI().RButtonUp();
			return true;
		case WM_RBUTTONDOWN:
			GetTgoUI().RButtonDown();
			return true;
		case WM_MOUSEMOVE:
			GetTgoUI().MouseHover();
			return true;
		}
		return false;
	}

}

/*
        TgoUI
*/

TgoUI::TgoUI()
{

}

TgoUI::~TgoUI()
{
        OnReleaseUI();
}

void TgoUI::OnInitUI()
{
        mUISprite.InitUISprite();
}

void TgoUI::OnUpdateUI( float dt )
{
	for ( int i = 0; i != mRootUI.size(); ++i ) {
		if( mRootUI[ i ]->IsActive() ) {
			mRootUI[ i ]->OnUpdate( dt );
		}
	}

        mUISprite.UpdateUISprite( dt );
}

void TgoUI::AddUI( TgoUIBase* ui )
{
        mRootUI.push_back( ui );
        SetupUI( ui );
}

void TgoUI::RenderUI()
{
        mUISprite.Render();
}

void TgoUI::OnReleaseUI()
{
        for ( int i = 0; i != mRootUI.size(); ++i ) {
                SAFE_DELETE( mRootUI[ i ] );
        }
		mUISprite.ReleaseUISprite();
}

void TgoUI::SetupUI( TgoUIBase* ui )
{
        mUISprite.AddUIEntity( new UIEntity( ui ) );
}

void TgoUI::LButtonDown()
{
	for( int i = 0; i != mRootUI.size(); ++i ) {
		if( mRootUI[ i ]->IsActive() ) {
			mRootUI[ i ]->LButtonDown();
		}
	}
}

void TgoUI::LButtonUp()
{
	for( int i = 0; i != mRootUI.size(); ++i ) {
		if( mRootUI[ i ]->IsActive() ) {
			mRootUI[ i ]->LButtonUp();
		}
	}
}

void TgoUI::RButtonDown()
{
	for( int i = 0; i != mRootUI.size(); ++i ) {
		if ( mRootUI[ i ]->IsActive() ) {
			mRootUI[ i ]->RButtonDown();
		}
	}
}

void TgoUI::RButtonUp()
{
	for ( int i = 0; i != mRootUI.size(); ++i ) {
		if ( mRootUI[ i ]->IsActive() ) {
			mRootUI[ i ]->RButtonUp();
		}
	}
}

void TgoUI::Click()
{
	for( int i = 0; i != mRootUI.size(); ++i ) {
		if ( mRootUI[ i ]->IsActive() ) {
			mRootUI[ i ]->Click();
		}
	}
}

void TgoUI::MouseHover()
{
        for( int i = 0; i != mRootUI.size(); ++i ) {
                mRootUI[ i ]->MouseHover();
        }
}


/*
        TgoUIBase
*/

TgoUIBase::TgoUIBase( D3DXVECTOR2 pos, 
					  UINT width, 
					  UINT height,
					  bool isRoot ):mIsActive( true ),
									mIsVisible( true ),
									mIsClicked( false ), 
									mIsMouseHover( false ),
									mIsLBtnDown( false ),
									mIsRBtnDown( false )
{
        mPos    = pos;
        mWidth  = width;
        mHeight = height;
        mIsRoot = isRoot;
        mParent = NULL;
}

TgoUIBase::~TgoUIBase()
{
        for ( int i = 0; i < mChildren.size(); ++i ) {
                SAFE_DELETE( mChildren[ i ] );
        }
        mChildren.clear();
}

void TgoUIBase::OnUpdate( float dt )
{
        for ( int i = 0; i != mChildren.size(); ++i ) {
                mChildren[ i ]->OnUpdate( dt );
        }
}

void TgoUIBase::AddChild( TgoUIBase* child )
{
        mChildren.push_back( child );
        child->SetParent( this );
        child->SetPos( child->GetPos() + this->GetPos() );
}

bool TgoUIBase::IsClicked()
{
        //TODO:figure out what is click event
        return false;
}

bool TgoUIBase::IsMouseHover()
{
        if ( InUI() ) {
                mIsMouseHover = true;
                return true;
        }
        mIsMouseHover = false;
        return false;
}

bool TgoUIBase::IsLButtonDown()
{
        if ( InUI() ) {
                mIsLBtnDown = true;
                return true;
        }
        mIsLBtnDown = false;
        return false;
}

bool TgoUIBase::IsRButtonDown()
{
        if ( InUI() ) {
                mIsRBtnDown = true;
                return true;
        }
        mIsRBtnDown = false;
        return false;
}

void TgoUIBase::MouseHover()
{
	if ( IsMouseHover() ) {
		for ( int i = 0; i != mChildren.size(); ++i ) {
			mChildren[ i ]->MouseHover();
		}
	}
}

void TgoUIBase::LButtonDown()
{
	if ( IsLButtonDown() ) {
		mIsLBtnDown = true;
		for( int i = 0; i != mChildren.size(); ++i ) {
			mChildren[ i ]->LButtonDown();
		}
		return;
	}
	mIsLBtnDown = false;
}

void TgoUIBase::LButtonUp()
{
	mIsLBtnDown = false;
	for( int i = 0; i != mChildren.size(); ++i ) {
		mChildren[ i ]->LButtonUp();
	}
}

void TgoUIBase::RButtonDown()
{
	if ( IsRButtonDown() ) {
		mIsRBtnDown = true;
		for( int i = 0; i != mChildren.size(); ++i ) {
			mChildren[ i ]->RButtonDown();
		}
		return;
	}
	mIsRBtnDown = false;
}

void TgoUIBase::RButtonUp()
{
	mIsRBtnDown = false;
	for( int i = 0; i != mChildren.size(); ++i ) {
		mChildren[ i ]->RButtonUp();
	}
}

bool TgoUIBase::InUI()
{
        UINT mouseX = Mouse::Instance()->X();
        UINT mouseY = Mouse::Instance()->Y();

        return !( mouseX > mPos.x + mWidth * 0.5f || mouseX < mPos.x - mWidth * 0.5f ||
                          mouseY > mPos.y + mHeight * 0.5f || mouseY < mPos.y - mHeight * 0.5f );
}

/*
        TgoUIButton
*/
TgoUIButton::TgoUISelector::TgoUISelector( D3DXVECTOR2 pos, 
                                                                                   UINT width, 
                                                                                   UINT height, 
                                                                                   bool isRoot ):TgoUIBase( pos, width, height, isRoot )
{
        Hide();
}

TgoUIButton::TgoUIButton( D3DXVECTOR2 pos,
						  UINT width, 
						  UINT height, 
						  bool isRoot ):TgoUIBase( pos, width, height, isRoot  ),
										mBtnDown ( false )
{
   
}

TgoUIButton::~TgoUIButton()
{

}

void TgoUIButton::MouseHover()
{
    if ( IsMouseHover() ) {
		SetTexture( mSelTexture );
		return;
    }
    SetTexture( mUnSelTexture );
}

void TgoUIButton::LButtonDown()
{
	mBtnDown = IsLButtonDown();
}

void TgoUIButton::LButtonUp()
{
	TgoUIBase::LButtonUp();
	mBtnDown = false;
}

/*
	TgoUIListBox
*/
TgoUIListBox::TgoUIListBox( D3DXVECTOR2 pos, 
							UINT width, 
							UINT height, 
							bool isRoot ):TgoUIBase( pos, width, height, isRoot ),
										  mItemHeight( height ),
										  mFocusItem( 1 ),
										  mRetItem( -1 )
{
	SetHeight( 0 );

	TgoUIBase* selector = new TgoUIBase( D3DXVECTOR2( -0.5f * ( mItemHeight + width ), 0 ),
										 height,
										 height );
	AddChild( selector );
	Hide();
}

void TgoUIListBox::SetSelectorTexture( string tex )
{
	GetChildren()[ 0 ]->SetTexture( tex );
}

UINT TgoUIListBox::GetFocusItem()
{
	return mRetItem;
}

void TgoUIListBox::AddItem( String item, string tex )
{
	SetHeight( GetHeight() + mItemHeight );

	D3DXVECTOR2 itemPos( 0, GetHeight() - mItemHeight );
	AddChild( new TgoUIButton( itemPos, GetWidth(), mItemHeight ) );
	GetChildren().back()->SetTexture( tex );
	GetChildren().back()->SetText( item );
}

void TgoUIListBox::MouseHover()
{
	for( int i = 1; i != GetChildren().size(); ++i ) {
		if ( GetChildren()[ i ]->IsMouseHover() ) {
			mFocusItem = i;
			break;
		}
	}

	D3DXVECTOR2 focusPos = GetChildren()[ mFocusItem ]->GetPos();
	GetChildren()[ 0 ]->SetPos( D3DXVECTOR2( focusPos.x - 0.5f * (GetWidth() + mItemHeight), focusPos.y ) );
}

void TgoUIListBox::LButtonDown()
{
	for ( int i = 1; i != GetChildren().size(); ++i ) {
		if ( GetChildren()[ i ]->IsLButtonDown() ) {
			mRetItem = i;
			return;
		}
	}
	mRetItem = -1;
}

void TgoUIListBox::LButtonUp()
{
	mRetItem = -1;
}

//////////////////////////////////////////////////////////////////////////

/*
        UIEntity
*/
UIEntity::UIEntity( TgoUIBase* ui )
{
        SetupUIEntity( ui );
}

UIEntity::~UIEntity()
{
        ReleaseEntity();
}

void UIEntity::UpdateEntity( float dt )
{
        D3DXVECTOR2 uiPos = mUIBase->GetPos();

        mEntity->SetPos( D3DXVECTOR3( uiPos.x, uiPos.y, top ) );
        mEntity->SetState( mUIBase->IsVisible() );
		mEntity->SetTexture( mUIBase->GetTexture() );

        for ( int i = 0; i != mChildren.size(); ++i ) {
                mChildren[ i ]->UpdateEntity( dt );
        }
}

void UIEntity::SetupUIEntity( TgoUIBase* ui )
{
        mUIBase = ui;

	D3DXVECTOR2 uiPos = ui->GetPos();
	UINT halfWidth	= ui->GetWidth() * 0.5f;
	UINT halfHeight	= ui->GetHeight() * 0.5f;
	D3DXVECTOR3 spriteCenter( halfWidth, halfHeight, 0 );
	D3DXVECTOR3 spritePos( uiPos.x, uiPos.y, top );

	mEntity = new Tgo2DEntity( spritePos, 0.0f );
	mEntity->SetTexture( ui->GetTexture() );
	mEntity->SetCenter( spriteCenter );

        for ( int i = 0; i != ui->GetChildren().size(); ++i )
                mChildren.push_back( new UIEntity( ui->GetChildren()[ i ] ) );
}

void UIEntity::ReleaseEntity()
{
        mUIBase = NULL;

        for ( int i = 0; i != mChildren.size(); ++i ) {
                mChildren[ i ]->ReleaseEntity();
                SAFE_DELETE( mChildren[ i ] );
        }
}

/*
        TgoUISprite
*/

TgoUISprite::TgoUISprite()
{

}

TgoUISprite::~TgoUISprite()
{
        ReleaseUISprite();
        SAFE_RELEASE( mUISprite );
}

void TgoUISprite::InitUISprite()
{
        HR( D3DXCreateSprite( RenderFrame::GetD3DDevice(), &mUISprite ) );
}

void TgoUISprite::UpdateUISprite( float dt )
{
	for ( int i = 0; i != mRootUIEntity.size(); ++i ) {
		if ( mRootUIEntity[ i ]->mUIBase->IsActive() ) {
			mRootUIEntity[ i ]->UpdateEntity( dt );
		}
	}
}

void TgoUISprite::Render()
{
	HR( RenderFrame::GetD3DDevice()->BeginScene() );
	HR( mUISprite->Begin( D3DXSPRITE_ALPHABLEND ) );
	
	for ( int i = 0; i != mRootUIEntity.size(); ++i ) {
		RenderUI( mRootUIEntity[ i ] );
	}
	
	HR( mUISprite->Flush() );
	HR( mUISprite->End() );
	HR( RenderFrame::GetD3DDevice()->EndScene() );
}

void TgoUISprite::RenderUI( UIEntity* ui )
{	
	TgoUIBase*	uiBase = ui->mUIBase;
	Tgo2DEntity* entity = ui->mEntity;
	if ( !uiBase->IsActive() ) {
		return;
	}

	if ( entity->IsVisible() ) {
		HR( mUISprite->Draw( entity->GetTexture(), 
							 NULL,
							 &entity->GetCenter(),
							 &entity->GetPos(),
							 D3DCOLOR_XRGB( 255, 255, 255 ) ) );
	}
						 
	RECT rect = RenderArea( uiBase->GetPos(), uiBase->GetWidth(), uiBase->GetHeight() );
	TGO::UIFont().DrawText( uiBase->GetText(), 
							RenderArea( uiBase->GetPos(), uiBase->GetWidth(), uiBase->GetHeight() ),
							0xFFFFFFFF, mUISprite );

        vector< UIEntity* > children = ui->mChildren;
        for ( int i = 0; i != children.size(); ++i ) {
                RenderUI( children[ i ] );
        }
}

void TgoUISprite::ReleaseUISprite()
{
        for ( int i = 0; i != mRootUIEntity.size(); ++i ) {
                SAFE_DELETE( mRootUIEntity[ i ] );
        }
}

void TgoUISprite::AddUIEntity( UIEntity* ui )
{
        mRootUIEntity.push_back( ui );
}